import logging
import os
import subprocess

import paramiko
from PyQt5.QtWidgets import QWidget


def run_command(command: str) -> str:
    """
    Выполнение команды и сохранение вывода в лог
    :param command: команда shell
    :return: результат работы команды
    """
    ret = subprocess.run(command, capture_output=True, shell=True)
    logging.info(f"[{command}]>{ret.stdout.decode()}")
    print(f"[{command}]>{ret.stdout.decode()}")
    return ret.stdout.decode()


def run_command_in_xterm(command: str):
    """
    Выполнение команды в xterm
    :param command: команда для выполнения
    """
    run_command(f'xterm -e "{command}"')


# def run_command_in_konsole(command: str):
#     """
#     Выполнение команды в новом окне терминала
#     :param command: команда для выполнения
#     """
#     run_command(f'konsole -e "{command}"')


def run_command_by_root(command: str):
    """
    Выполнение команды с правами root в xterm
    @param command: команда для выполнения
    @return: содержимое вывода
    """
    temp_file = run_command(
        f't=$(mktemp); xterm -e \'echo "Введите пароль суперпользователя на этом компьютере: " ; '
        f'su - root -c "{command}" 2>&1 | tee \'$t; echo $t').strip()
    try:
        res = open(temp_file, 'r').read().strip()
        os.remove(temp_file)
        return res
    except Exception as e:
        logging.info(f'В процессе чтения из временного файла возникла ошибка: {e}')
        return ''


def get_mac_address(host):
    """
    Получение MAC-адреса удаленного хоста
    :param host: хост
    :return: MAC-адрес хоста
    """
    get_nmcli = run_command(
        f'ssh root@{host.hostname} nmcli dev show'
    )
    if get_nmcli:
        connected = 0
        for line in get_nmcli.split('\n'):
            if 'GENERAL.DEVICE' in line:  # описание нового устройства
                connected = 0
            if 'GENERAL.TYPE' in line and ('wifi' in line or 'ethernet' in line):  # wi-fi или ethernet
                connected += 1
            if 'GENERAL.HWADDR' in line and ':' in line:  # указан корректный MAC-адрес
                connected += 1
                hwaddr = line.split()[-1].strip()
            if 'GENERAL.STATE' in line and '100' in line:  # подключено
                if connected == 2:  # wi-fi или ethernet с указанным MAC-адресом
                    logging.info(f"Получен MAC-адрес {hwaddr} для {host.hostname}")
                    return hwaddr

    return ""


def test_ssh(host) -> bool:
    """
    Проверка ssh для пользователя root на удаленном хосте
    :param host: объект Host
    :return: True, если удалось подключиться, иначе False
    """
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.load_system_host_keys()
    try:
        ssh.connect(hostname=host.hostname, port=22, timeout=1, username=host.admin_login, password=host.admin_pass)
        return True
    except Exception as e:
        logging.info(f"Не удалось подключиться по ssh {host.admin_login}@{host.hostname}: {e}")
        return False
    finally:
        ssh.close()


def test_ping(host) -> bool:
    """
    Проверка подключения к удаленному хосту
    :param host: строка с адресом хоста
    :return: True, если ping прошёл, иначе False
    """
    result = subprocess.run(['ping', '-c1', host], stdout=subprocess.PIPE)
    if result.returncode == 0:
        logging.info(f"ping: {host}: УСПЕШНОЕ СОЕДИНЕНИЕ {result=} {result.returncode=}")
        return True
    elif result.returncode == 2:
        logging.info(f"ping: {host}: {result=} {result.returncode=}")
        return False
    else:
        logging.info(host + f" неизвестная ошибка {result=} {result.returncode=}")
        return False


def check_student_on_host(host) -> bool:
    """
    Проверка наличия директории пользователя student на удаленном хосте
    :param host: объект Host
    :return: True, если есть указанный аккаунт, иначе False
    """
    check = run_command(f"ssh root@{host.hostname} id -u {host.student_login}; echo $?").strip()
    return True if check.endswith('0') else False


# Получение имени компьютера и текущего пользователя
this_host = run_command('hostname').strip()
user = run_command('whoami').strip()


class CompKabSolutionWindow(QWidget):
    pass


def poweroff():
    """
    Выключение сервера
    """
    run_command('poweroff')
